﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace RQX.Common.Framework.Extension
{
    /// <summary>
    /// 公共扩展类
    /// </summary>
    public static class CommonExtension
    {
        #region byte
        public static char ToChar(this byte b)
        {
            return Convert.ToChar(b);
        }
        #endregion

        #region byte[]
        /// <summary>
        /// 将byte转为Default的字符串
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static string ToDefault(this byte[] buffer)
        {
            return Encoding.Default.GetString(buffer);
        }
        /// <summary>
        /// 将byte转为utf8的字符串
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static string ToUTF8(this byte[] buffer)
        {
            return Encoding.UTF8.GetString(buffer);
        }
        /// <summary>
        /// 将byte转为16进制
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static string ToHex(this byte[] buffer, string splitChar = "")
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in buffer)
            {
                sb.Append($"{splitChar}{item:x2}");
            }
            return sb.ToString().Substring(splitChar.Length);
        }
        /// <summary>
        /// 将byte数组转为字符串
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static string ToString(this byte[] buffer, Encoding encoding)
        {
            return encoding.GetString(buffer);
        }
        #endregion

        #region int
        /// <summary>
        /// 判断int数值是否不在数组中
        /// </summary>
        /// <param name="integer"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool IsNotIn(this int integer, params int[] data)
        {
            foreach (var item in data)
            {
                if (integer == item)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 判断int数值是否在数组中
        /// </summary>
        /// <param name="integer"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool IsIn(this int integer, params int[] data)
        {
            foreach (var item in data)
            {
                if (integer == item)
                {
                    return true;
                }
            }
            return false;
        }
        #endregion

        #region string
        /// <summary>
        /// 将Default编码的字符串转为byte数组
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] DefaultToByte(this string str)
        {
            return Encoding.Default.GetBytes(str);
        }
        /// <summary>
        /// 将utf8编码的字符串转为byte数组
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] UTF8ToByte(this string str)
        {
            return Encoding.UTF8.GetBytes(str);
        }
        /// <summary>
        /// 截取字符串左侧指定长度
        /// </summary>
        /// <param name="str"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static string Left(this string str, int len)
        {
            if (str == null || str.Length < len)
            {
                return str;
            }
            return str.Substring(0, len);
        }
        /// <summary>
        /// 去掉末尾的字符串
        /// </summary>
        /// <param name="baseStr"></param>
        /// <param name="removeStrList"></param>
        /// <returns></returns>
        public static string RemoveEndStr(this string baseStr, params string[] removeStrList)
        {
            if (baseStr == null)
            {
                return null;
            }

            if (baseStr == string.Empty)
            {
                return string.Empty;
            }

            if (removeStrList.IsNullOrEmpty())
            {
                return baseStr;
            }

            for(var i = 0; i < removeStrList.Length; i++)
            {
                if (baseStr.EndsWith(removeStrList[i]))
                {
                    baseStr = baseStr.Left(baseStr.Length - removeStrList[i].Length);
                    i = -1;
                }
            }

            return baseStr;
        }
        /// <summary>
        /// 判断字符串是否不在数据中
        /// </summary>
        /// <param name="str"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool IsNotIn(this string str, params string[] data)
        {
            foreach (var item in data)
            {
                if (str == item)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 判断字符串是否在数组中，需要全等
        /// </summary>
        /// <param name="str"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool IsIn(this string str, params string[] data)
        {
            foreach (var item in data)
            {
                if (str == item)
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 通过名称获取type
        /// </summary>
        /// <param name="fullName"></param>
        /// <returns></returns>
        public static Type GetCurrentType(this string fullName)
        {
            return AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(a => a.GetTypes())
                        .Where(u => fullName.Equals(u.FullName))
                        .ToList().FirstOrDefault();
        }
        /// <summary>
        /// 判断string是否为空或者null
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }
        /// <summary>
        /// 判断string是否非空
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNotNullOrEmpty(this string str)
        {
            return !string.IsNullOrEmpty(str);
        }
        /// <summary>
        /// 包含其中一项则返回true
        /// </summary>
        /// <param name="str"></param>
        /// <param name="filterList"></param>
        /// <returns></returns>
        public static bool Contains(this string str, params string[] filterList)
        {
            foreach (var filter in filterList)
            {
                if (str.Contains(filter)) return true;
            }
            return false;
        }
        /// <summary>
        /// 全部包含才返回true
        /// </summary>
        /// <param name="str"></param>
        /// <param name="filterList"></param>
        /// <returns></returns>
        public static bool ContainsAll(this string str, params string[] filterList)
        {
            foreach (var filter in filterList)
            {
                if (!str.Contains(filter)) return false;
            }
            return true;
        }
        /// <summary>
        /// 16进制表示的字符串，转为byte数组
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] HexStringToByte(this string str)
        {
            str = str.Replace(" ", "");
            if (str.Length % 2 != 0) str += " ";
            var length = str.Length / 2;
            var buffer = new byte[length];
            for(var i = 0; i < length; i++)
            {
                buffer[i] = Convert.ToByte(str.Substring(i * 2, 2), 16); 
            }
            return buffer;
        }
        /// <summary>
        /// 字符串转为byte数组
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] ToByte(this string str, Encoding encoding)
        {
            return encoding.GetBytes(str);
        }


        #endregion

        #region object
        /// <summary>
        /// 判断obj是否为空
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNull(this object obj)
        {
            return obj == null;
        }
        /// <summary>
        /// 判断obj不为空
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNotNull(this object obj)
        {
            return obj != null;
        }
        ///// <summary>
        ///// 列表拷贝
        ///// </summary>
        ///// <typeparam name="TOut"></typeparam>
        ///// <param name="objSource"></param>
        ///// <param name="objTarget"></param>
        ///// <param name="ignoredProperties"></param>
        ///// <returns></returns>
        //public static IEnumerable<TOut> CopyToList<TOut>(this object objSource, IEnumerable<TOut> objTarget, params string[] ignoredProperties)
        //{
        //    try
        //    {
        //        var sourceList = objSource as IEnumerable<object>;
        //        sourceList.ForEach(source =>
        //        {
        //            var obj = default(TOut);
        //            objTarget.Append(source.CopyTo(obj, ignoredProperties));
        //        });
        //        return objTarget;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw new Exception("复制失败，请手工赋值" + ex.Message);
        //    }

        //}
        /// <summary>
        /// 对象属性复制
        /// </summary>
        /// <typeparam name="TOut">输出类型</typeparam>
        /// <param name="objSource">输入</param>
        /// <param name="objTarget">输出</param>
        /// <param name="ignoredProperties"><paramref name="objTarget"/> 所忽略复制的属性</param>
        /// <returns></returns>
        public static TOut CopyTo<TOut>(this object objSource, TOut objTarget, params string[] ignoredProperties)
        {
            try
            {
                TOut tOut = objTarget;
                var tInType = objSource.GetType();
                foreach (var itemOut in tOut.GetType().GetProperties())
                {
                    if (ignoredProperties.Contains(itemOut.Name)) continue;
                    var itemIn = tInType.GetProperty(itemOut.Name);//根据属性名称来得到对象的属性信息
                    if (itemIn != null)
                    {
                        try
                        {
                            itemOut.SetValue(tOut, itemIn.GetValue(objSource));//从（tIn）中获取属性值并赋值给StudentSecond（tOut）对象
                        }
                        catch { }
                    }
                }
                return tOut;
            }
            catch (Exception ex)
            {
                throw new Exception("复制失败，请手工赋值" + ex.Message);
            }
        }
        /// <summary>
        /// 对象属性复制
        /// </summary>
        /// <typeparam name="TTarget">输出类型</typeparam>
        /// <typeparam name="TSource">源类型</typeparam>
        /// <param name="objTarget">输入</param>
        /// <param name="objSource">输出</param>
        /// <param name="ignoredProperties"><paramref name="objSource"/> 所忽略复制的属性</param>
        /// <returns></returns>
        public static TTarget CopyFrom<TTarget, TSource>(this TTarget objTarget, TSource objSource, params string[] ignoredProperties)
        {
            try
            {
                TTarget tOut = objTarget;
                var tInType = objSource.GetType();
                foreach (var itemOut in tOut.GetType().GetProperties())
                {
                    if (ignoredProperties.Contains(itemOut.Name)) continue;
                    var itemIn = tInType.GetProperty(itemOut.Name);//根据属性名称来得到对象的属性信息
                    if (itemIn != null)
                    {
                        var value = itemIn.GetValue(objSource);
                        if (value != null)
                        {
                            itemOut.SetValue(tOut, value);
                        }
                    }
                }
                return tOut;
            }
            catch (Exception ex)
            {
                throw new Exception("复制失败，请手工赋值" + ex.Message);
            }
        }
        /// <summary>
        /// 获取对象属性对应的值
        /// </summary>
        /// <param name="info"></param>
        /// <param name="field">属性名称</param>
        /// <returns></returns>
        public static object GetPropertyValue(this object info, string field)
        {
            if (info == null) return null;
            Type t = info.GetType();
            IEnumerable<PropertyInfo> property = from pi in t.GetProperties() where pi.Name.ToLower() == field.ToLower() select pi;
            if (property.Count() == 0) throw new Exception("获取属性值错误，没有对应的属性");
            return property.First().GetValue(info, null);
        }
        #endregion

        #region ICollection
        /// <summary>
        /// 判断集合是否为空
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty<T>(this ICollection<T> source)
        {
            return source == null || source.Count <= 0;
        }
        #endregion

        #region IEnumerable
        /// <summary>
        /// 判断集合是否为空
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
        {
            return source == null || source.Count() <= 0;
        }
        /// <summary>
        /// 集合便利，执行函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        /// <param name="action"></param>
        public static void ForEach<T>(this IEnumerable<T> query, Action<T> action)
        {
            foreach (var item in query)
            {
                action(item);
            }
        }
        /// <summary>
        /// 集合便利，查找指定项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static T Find<T>(this IEnumerable<T> query, Func<T, bool> func)
        {
            foreach (var item in query)
            {
                if (func(item))
                {
                    return item;
                }
            }
            return default;
        }
        #endregion
    }
}
